#!/bin/bash
## "A bash and awk script for generating a endless scoreboard web page.
## written by demure
## https://notabug.org/demure/scripts/src/master/endlessh_scoreboard.sh
## 
## 2019-04-03: Initial Version.

## Dependencies:
## gawk
## bc
## geoiplookup
## sha512sum

## Initialize
declare -a ARRAY
declare Last
declare LastHost
declare HostCount
declare MaxTime
declare MinTime
declare SumTime
declare x
declare y
declare Geo

## Parse endlessh log, keep last 7 days, output host and time spent, sort by host, store in array
#ARRAY=($(TZ=UTC awk -v CUTOFF=$(date --date="-7 days" +%s) '/CLOSE/ {match($0,/^(.*T.*Z).*host=([0-9a-f:\.]+).*time=([0-9\.]+)/,m); command="date -d" m[1] " +%s"; command | getline m[1]; close(command)}{if(m[1]>CUTOFF){print m[2],m[3]}}' /var/log/endlessh.log | sort -k1))
## Doesn't account for ipv6
ARRAY=($(TZ=UTC awk -v CUTOFF=$(date --date="-7 days" +%s) '/CLOSE/ {match($0,/^(.*T.*Z).*host=::ffff:([0-9a-f:\.]+).*time=([0-9\.]+)/,m); command="date -d" m[1] " +%s"; command | getline m[1]; close(command)}{if(m[1]>CUTOFF){print m[2],m[3]}}' /var/log/endlessh.log 2>/dev/null | sort -k1))

## Get the last array element position
Last="$(echo "${!ARRAY[@]}" | awk '{print $NF}')"

## Print HTML Beginning
HTML1=$(cat <<-END
<html><center><body>

<style> table {border-spacing: 0; border: 1px solid black; font-family: monospace;} th {cursor: pointer;} th, td {border: 1px solid black; border-collapse: collapse;}</style>
        <h2>Tar Pit Score Board</h2>

    <p>Here is a little Score Board of <strike>ssh</strike> player attempts from the last seven days. <BR>To "keep things fair", players who try too many times are given a time out. <BR>All times are in seconds, and hosts are hashed for 'privacy'. <BR> Number colmnus may be sorted by clicking.</p>

        <table id="myTable">
        <tr><th onclick="sortTable(0)">Host (hashed)</th><th onclick="sortTable(1)">Geo Location</th><th onclick="sortTable(2)">Attempts</th><th onclick="sortTable(3)">Shortest Conn</th><th onclick="sortTable(4)">Longest Conn</th><th onclick="sortTable(5)">Average Conn</th><th onclick="sortTable(6)">Total Conn</th></tr>

END
)

echo "${HTML1}"

## iterate over array
for i in "${!ARRAY[@]}"; do

    x="${ARRAY[i]}"             ## Hold current host
    y="${ARRAY[$((i+1))]}"      ## Hold current time spent

    ## Act on even, since the array length is doubled
    if [[ $((i%2)) -eq 0 ]]; then
        if [ "${x}" == "${LastHost}" ]; then
            HostCount=$(($HostCount+1))

            #if [ "${y}" > "${MaxTime}" ]; then
            if (( $(echo "${y} > ${MaxTime}" | bc) )); then
                #echo "$MaxTime -> $y"
                MaxTime="${y}"
            fi
            if (( $(echo "${y} < ${MaxTime}" | bc) )); then
            #if [ "${y}" < "${MinTime}" ]; then
                MinTime="${y}"
            fi
            SumTime=$(echo "${SumTime} + ${y}" | bc)
          else
            if [ ! -z ${LastHost} ]; then
                Geo="$(geoiplookup ${LastHost} | awk '/Country/ {match($0, /Geo.*: [A-Z]+, (.*)/, m); print m[1]}')"
                #Geo="$(geoiplookup ${LastHost} | awk '/Country/ {match($0, /Geo.*: (.*)/, m); print m[1]}')"

                #echo "Host $(echo ${LastHost} | sha512sum | cut -c1-16), Geo ${Geo}, Times ${HostCount}, Min ${MinTime}, Max ${MaxTime}, Average $(echo "${SumTime} / ${HostCount}" | bc), Total ${SumTime}"
                echo "<tr><td>$(echo ${LastHost} | sha512sum | cut -c1-16)</td><td>${Geo}</td><td align=right>${HostCount}</td><td align=right>${MinTime}</td><td align=right>${MaxTime}</td><td align=right>$(echo "${SumTime} / ${HostCount}" | bc)</td><td align=right>${SumTime}</td></tr>"
            fi


            ## Make new tracking 
            LastHost="${x}"
            HostCount=1
            MaxTime="${y}"
            MinTime="${y}"
            SumTime="${y}"
            Geo=""


        fi
    fi
done

## TODO: Make sure last round printed


## TODO: Add "banned players" section using f2b jail ban list

## Print HTML end
HTML3=$(cat <<-END
    </table>
    <p>This page is brought to you by bash, gawk, and geoiplookup.</p>
    <p><b>Last updated $(date -u)</b></p>

    <script>
    function sortTable(n) {
        var table, rows, switching, i, x, y, shouldSwitch, dir, switchcount = 0;
        table = document.getElementById("myTable");
        switching = true;
        // Set the sorting direction to ascending:
        dir = "asc"; 
        /* Make a loop that will continue until
        no switching has been done: */
        while (switching) {
            // Start by saying: no switching is done:
            switching = false;
            rows = table.rows;
            /* Loop through all table rows (except the
            first, which contains table headers): */
            for (i = 1; i < (rows.length - 1); i++) {
                // Start by saying there should be no switching:
                shouldSwitch = false;
                /* Get the two elements you want to compare,
                one from current row and one from the next: */
                x = rows[i].getElementsByTagName("TD")[n];
                y = rows[i + 1].getElementsByTagName("TD")[n];
                /* Check if the two rows should switch place,
                based on the direction, asc or desc: */
                if (dir == "asc") {
                    if (Number(x.innerHTML) < Number(y.innerHTML)) {
                        // If so, mark as a switch and break the loop:
                        shouldSwitch = true;
                        break;
                    }
                } else if (dir == "desc") {
                    if (Number(x.innerHTML) > Number(y.innerHTML)) {
                        // If so, mark as a switch and break the loop:
                        shouldSwitch = true;
                        break;
                    }
                }
            }
            if (shouldSwitch) {
                /* If a switch has been marked, make the switch
                and mark that a switch has been done: */
                rows[i].parentNode.insertBefore(rows[i + 1], rows[i]);
                switching = true;
                // Each time a switch is done, increase this count by 1:
                switchcount ++; 
            } else {
                /* If no switching has been done AND the direction is "asc",
                set the direction to "desc" and run the while loop again. */
                if (switchcount == 0 && dir == "asc") {
                    dir = "desc";
                    switching = true;
                }
            }
        }
    }
    </script>

    </body></center></html>
END
)

echo "${HTML3}"
#echo "--------------------"     ## DEBUG
